/**
 * 图片管理模块
 * 负责图片的存储、检索、向量化搜索等功能
 */
import fs from 'fs/promises'
import path from 'path'
import { v4 as uuidv4 } from 'uuid'
import OpenAI from 'openai'
import dotenv from 'dotenv'
import fetch from 'node-fetch'

dotenv.config()

const IMAGES_DIR = './uploads/images'
const METADATA_FILE = './uploads/metadata.json'
const CHROMA_API_URL = process.env.CHROMA_API_URL || 'http://localhost:8001'

class ImageManager {
  constructor() {
    this.embeddingClient = null
    this.initialized = false
    this.useChromaDB = false
    this.metadata = []
  }

  async initialize() {
    if (this.initialized) return

    console.log('🔄 正在初始化 ImageManager...')

    // 创建上传目录
    await this.ensureDirectories()

    // 初始化嵌入模型客户端
    this.initializeEmbeddingClient()

    // 加载元数据
    await this.loadMetadata()

    // 测试 ChromaDB 连接
    await this.testChromaDBConnection()

    this.initialized = true
    console.log(`✅ ImageManager 初始化完成，当前有 ${this.metadata.length} 张图片`)
  }

  async ensureDirectories() {
    try {
      await fs.mkdir(IMAGES_DIR, { recursive: true })
      await fs.mkdir('./uploads', { recursive: true })
      console.log('✅ 上传目录已创建')
    } catch (err) {
      console.error('❌ 创建上传目录失败:', err.message)
    }
  }

  initializeEmbeddingClient() {
    if (process.env.ALIYUN_API_KEY && process.env.ALIYUN_BASE_URL) {
      this.embeddingClient = new OpenAI({
        apiKey: process.env.ALIYUN_API_KEY,
        baseURL: process.env.ALIYUN_BASE_URL
      })
      console.log('✅ 已配置阿里云嵌入模型客户端（图片）')
    } else if (process.env.OPENAI_KEY) {
      this.embeddingClient = new OpenAI({
        apiKey: process.env.OPENAI_KEY
      })
      console.log('✅ 已配置 OpenAI 嵌入模型客户端（图片）')
    } else {
      console.warn('⚠️ 未配置嵌入模型，相似图片搜索功能将受限')
    }
  }

  async testChromaDBConnection() {
    try {
      const response = await fetch(`${CHROMA_API_URL}/api/health`, {
        signal: AbortSignal.timeout(3000)
      })
      
      if (response.ok) {
        this.useChromaDB = true
        console.log('✅ [ImageManager] ChromaDB 连接成功')
      }
    } catch (error) {
      this.useChromaDB = false
      console.warn('⚠️ [ImageManager] ChromaDB 不可用，相似图片搜索将使用简单匹配')
    }
  }

  async loadMetadata() {
    try {
      const data = await fs.readFile(METADATA_FILE, 'utf8')
      this.metadata = JSON.parse(data)
      console.log(`📂 已加载 ${this.metadata.length} 条图片元数据`)
    } catch (err) {
      if (err.code === 'ENOENT') {
        this.metadata = []
        await this.saveMetadata()
        console.log('📂 创建新的元数据文件')
      } else {
        console.error('❌ 加载元数据失败:', err.message)
        this.metadata = []
      }
    }
  }

  async saveMetadata() {
    try {
      await fs.writeFile(METADATA_FILE, JSON.stringify(this.metadata, null, 2))
    } catch (err) {
      console.error('❌ 保存元数据失败:', err.message)
    }
  }

  // 生成图片描述的嵌入向量
  async generateEmbedding(text) {
    if (this.embeddingClient) {
      try {
        const model = process.env.EMBEDDING_MODEL || 'text-embedding-v2'
        const response = await this.embeddingClient.embeddings.create({
          model: model,
          input: text.substring(0, 2000)
        })
        return response.data[0].embedding
      } catch (err) {
        console.error('❌ 生成嵌入向量失败:', err.message)
        return this.simpleEmbedding(text)
      }
    }
    return this.simpleEmbedding(text)
  }

  // 简单的备用嵌入方法
  simpleEmbedding(text) {
    const dim = 384
    const vector = new Array(dim).fill(0)
    for (let i = 0; i < text.length && i < dim; i++) {
      const charCode = text.charCodeAt(i)
      vector[i % dim] += charCode / 1000
      vector[(i + 100) % dim] += (i / text.length)
    }
    const magnitude = Math.sqrt(vector.reduce((sum, val) => sum + val * val, 0))
    return vector.map(val => magnitude > 0 ? val / magnitude : 0)
  }

  // 保存图片
  async saveImage({ name, base64Data, tags = [], description = '', detections = [], aiProcessed = false }) {
    if (!this.initialized) await this.initialize()

    const imageId = uuidv4()
    const ext = this.getImageExtension(base64Data)
    const filename = `${imageId}${ext}`
    const filepath = path.join(IMAGES_DIR, filename)

    try {
      // 保存图片文件
      const base64Match = base64Data.match(/^data:image\/\w+;base64,(.+)$/)
      const buffer = Buffer.from(base64Match ? base64Match[1] : base64Data, 'base64')
      await fs.writeFile(filepath, buffer)

      // 生成文本描述用于向量化
      const textForEmbedding = `${name} ${tags.join(' ')} ${description}`
      const embedding = await this.generateEmbedding(textForEmbedding)

      // 创建元数据
      const metadata = {
        id: imageId,
        name,
        filename,
        filepath: `/uploads/images/${filename}`,
        tags,
        description,
        detections,
        aiProcessed,
        createdAt: new Date().toISOString(),
        size: buffer.length
      }

      this.metadata.push(metadata)
      await this.saveMetadata()

      console.log(`✅ 图片已保存: ${name} (${imageId})`)
      return metadata
    } catch (err) {
      console.error('❌ 保存图片失败:', err.message)
      throw err
    }
  }

  getImageExtension(base64Data) {
    if (base64Data.includes('image/png')) return '.png'
    if (base64Data.includes('image/jpeg') || base64Data.includes('image/jpg')) return '.jpg'
    if (base64Data.includes('image/gif')) return '.gif'
    if (base64Data.includes('image/webp')) return '.webp'
    return '.jpg'
  }

  // 将图片文件转换为 base64
  async imageToBase64(filepath) {
    try {
      const fullPath = path.join('.', filepath)
      const buffer = await fs.readFile(fullPath)
      const base64 = buffer.toString('base64')
      const ext = path.extname(filepath).toLowerCase()
      const mimeTypes = {
        '.png': 'image/png',
        '.jpg': 'image/jpeg',
        '.jpeg': 'image/jpeg',
        '.gif': 'image/gif',
        '.webp': 'image/webp'
      }
      const mimeType = mimeTypes[ext] || 'image/jpeg'
      return `data:${mimeType};base64,${base64}`
    } catch (err) {
      console.error(`❌ 转换图片失败 ${filepath}:`, err.message)
      return null
    }
  }

  // 为图片添加 dataUrl 字段
  async addDataUrlToImage(img) {
    if (img.filepath) {
      const dataUrl = await this.imageToBase64(img.filepath)
      return { ...img, dataUrl, url: img.filepath }
    }
    return img
  }

  // 列出所有图片
  async listImages() {
    if (!this.initialized) await this.initialize()
    const sorted = [...this.metadata].sort((a, b) => 
      new Date(b.createdAt) - new Date(a.createdAt)
    )
    
    // 为每张图片添加 dataUrl
    const withDataUrl = await Promise.all(
      sorted.map(img => this.addDataUrlToImage(img))
    )
    
    return withDataUrl
  }

  // 搜索图片
  async searchImages({ query = '', tag = '', dateRange = 'all', sortBy = 'createdAt' }) {
    if (!this.initialized) await this.initialize()

    console.log(`🔍 [ImageManager] 搜索参数: query="${query}", tag="${tag}", dateRange="${dateRange}"`)

    let results = [...this.metadata]

    // 标签过滤
    if (tag && tag !== 'all') {
      results = results.filter(img => 
        img.tags && img.tags.some(t => t === tag || t.includes(tag))
      )
      console.log(`   标签过滤后: ${results.length} 张`)
    }

    // 关键词搜索
    if (query.trim()) {
      const qLower = query.toLowerCase()
      results = results.filter(img =>
        (img.name || '').toLowerCase().includes(qLower) ||
        (img.description || '').toLowerCase().includes(qLower) ||
        (img.tags && img.tags.join(',').toLowerCase().includes(qLower))
      )
      console.log(`   关键词过滤后: ${results.length} 张`)
    }

    // 日期范围过滤
    if (dateRange !== 'all') {
      const now = new Date()
      const ranges = {
        today: 24 * 60 * 60 * 1000,
        week: 7 * 24 * 60 * 60 * 1000,
        month: 30 * 24 * 60 * 60 * 1000
      }
      const timeThreshold = now.getTime() - (ranges[dateRange] || 0)
      results = results.filter(img => 
        new Date(img.createdAt).getTime() >= timeThreshold
      )
      console.log(`   日期过滤后: ${results.length} 张`)
    }

    // 排序
    if (sortBy === 'name') {
      results.sort((a, b) => (a.name || '').localeCompare(b.name || ''))
    } else {
      results.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt))
    }

    // 为每张图片添加 dataUrl
    const withDataUrl = await Promise.all(
      results.map(img => this.addDataUrlToImage(img))
    )

    console.log(`✅ [ImageManager] 返回 ${withDataUrl.length} 张图片`)
    return withDataUrl
  }

  // 相似图片搜索
  async searchSimilarImages(imageId, limit = 5) {
    if (!this.initialized) await this.initialize()

    const sourceImage = this.metadata.find(img => img.id === imageId)
    if (!sourceImage) {
      throw new Error('源图片不存在')
    }

    // 简单匹配
    const similar = this.metadata
      .filter(img => img.id !== imageId)
      .map(img => {
        let score = 0
        if (sourceImage.tags && img.tags) {
          const commonTags = sourceImage.tags.filter(t => img.tags.includes(t))
          score += commonTags.length * 10
        }
        if (sourceImage.detections && img.detections) {
          const sourceClasses = sourceImage.detections.map(d => d.class)
          const imgClasses = img.detections.map(d => d.class)
          const commonClasses = sourceClasses.filter(c => imgClasses.includes(c))
          score += commonClasses.length * 5
        }
        return { ...img, similarity: score }
      })
      .sort((a, b) => b.similarity - a.similarity)
      .slice(0, limit)

    return similar
  }

  // 删除图片
  async deleteImage(imageId) {
    if (!this.initialized) await this.initialize()

    const index = this.metadata.findIndex(img => img.id === imageId)
    if (index === -1) {
      throw new Error('图片不存在')
    }

    const image = this.metadata[index]

    try {
      const filepath = path.join(IMAGES_DIR, image.filename)
      await fs.unlink(filepath).catch(() => {})

      this.metadata.splice(index, 1)
      await this.saveMetadata()

      console.log(`✅ 图片已删除: ${imageId}`)
      return true
    } catch (err) {
      console.error('❌ 删除图片失败:', err.message)
      throw err
    }
  }

  // 获取统计信息
  async getStatistics() {
    if (!this.initialized) await this.initialize()

    const tagCounts = {}
    let defectCount = 0
    let normalCount = 0
    let aiProcessedCount = 0
    let totalSize = 0

    this.metadata.forEach(img => {
      if (img.aiProcessed) aiProcessedCount++
      if (img.size) totalSize += img.size

      if (img.tags) {
        img.tags.forEach(tag => {
          tagCounts[tag] = (tagCounts[tag] || 0) + 1
        })
        
        const hasDefect = img.tags.some(tag => tag !== '正常')
        if (hasDefect) {
          defectCount++
        } else {
          normalCount++
        }
      } else if (img.detections && img.detections.length > 0) {
        defectCount++
      } else {
        normalCount++
      }
    })

    return {
      total: this.metadata.length,
      defectCount,
      normalCount,
      aiProcessedCount,
      totalSize,
      tags: tagCounts,
      avgConfidence: this.metadata.reduce((sum, img) => {
        if (img.detections && img.detections.length > 0) {
          const avgConf = img.detections.reduce((s, d) => s + (d.confidence || 0), 0) / img.detections.length
          return sum + avgConf
        }
        return sum
      }, 0) / Math.max(this.metadata.length, 1)
    }
  }

  // 获取图片详情
  async getImage(imageId) {
    if (!this.initialized) await this.initialize()
    return this.metadata.find(img => img.id === imageId)
  }

  // 更新图片元数据
  async updateImage(imageId, updates) {
    if (!this.initialized) await this.initialize()

    const index = this.metadata.findIndex(img => img.id === imageId)
    if (index === -1) {
      throw new Error('图片不存在')
    }

    this.metadata[index] = {
      ...this.metadata[index],
      ...updates,
      id: imageId,
      updatedAt: new Date().toISOString()
    }

    await this.saveMetadata()
    return this.metadata[index]
  }
}

const imageManager = new ImageManager()
export default imageManager
